package com.caishi.lkx.course.api;

import cn.hutool.core.util.StrUtil;
import cn.hutool.json.JSONObject;
import com.aliyun.vod20170321.models.GetPlayInfoResponseBody;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.caishi.lkx.common.AclResultCode;
import com.caishi.lkx.common.AdminBaseApi;
import com.caishi.lkx.common.aliyun.AliyunVideoPluginsExt;
import com.caishi.lkx.course.dto.VideoHandoutDto;
import com.caishi.lkx.course.dto.VideoSyncDto;
import com.caishi.lkx.course.mapper.VideoInfoMapper;
import com.caishi.lkx.course.mapper.VideoRecordsMapper;
import com.caishi.lkx.course.model.*;
import com.caishi.lkx.course.service.IVideoChapterReService;
import com.caishi.lkx.course.service.IVideoChapterService;
import com.caishi.lkx.course.service.IVideoHandoutService;
import com.caishi.lkx.course.service.IVideoInfoService;
import com.caishi.lkx.exam.model.CategoryModel;
import com.caishi.lkx.exam.records.RecordsGetDataService;
import com.caishi.lkx.exam.records.RecordsSetDataService;
import com.caishi.lkx.exam.records.dto.CountVideoRecordsDto;
import com.caishi.lkx.exam.records.dto.VideoRecordsDto;
import com.caishi.lkx.exam.records.dto.VideoRecordsDtoItem;
import com.caishi.lkx.exam.records.oss.OssRecordsService;
import com.caishi.lkx.exam.service.ICategoryService;
import com.caishi.lkx.exam.service.IColumnService;
import com.caishi.lkx.exam.service.IExColumnConfigReService;
import com.zzw.common.entity.impl.BaseIntEntity;
import com.zzw.common.exception.BizException;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.tags.Tag;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;

import javax.annotation.Resource;
import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;


/**
 * @author lkx
 * &#064;date  2024/5/27
 * &#064;description
 */
@Slf4j
@Tag(name = "视频相关接口")
@RestController
@RequestMapping("/kc/course/video")
public class VideoInfoApi extends AdminBaseApi<IVideoInfoService, VideoInfoModel, String> {

    @Resource
    private VideoRecordsMapper videoRecordsMapper;
    @Resource
    private IVideoInfoService videoInfoService;

    @Resource
    private ICategoryService categoryService;

    @Resource
    private IVideoChapterService videoChapterService;

    @Resource
    private IVideoChapterReService videoChapterReService;

    @Resource
    private IVideoHandoutService videoHandoutService;

    @Resource
    private RecordsGetDataService recordsGetDataService;

    @Resource
    private RecordsSetDataService recordsSetDataService;

    @Resource
    private IExColumnConfigReService columnConfigReService;

    @Resource
    private IColumnService columnService;

    @Autowired
    private AliyunVideoPluginsExt aliyunVideoPluginsExt;

    @Resource
    private OssRecordsService ossRecordsService;

    @Override
    public IVideoInfoService loadService() {
        return videoInfoService;
    }

    @PostMapping("/sync")
    @Operation(summary = "阿里云视频同步")
    public Boolean sync(@RequestBody VideoSyncDto videoSyncDto) {
        loadService().insertBatch(videoSyncDto);
        return true;
    }

    @Override
    protected List<VideoInfoModel> listCover(List<VideoInfoModel> result, JSONObject otherParam) {
        Map<Long, String> cateNameMap;
        Map<String, String> chapterNameMap;
        if (!result.isEmpty()) {
            List<Long> categoryIds = result.stream().map(VideoInfoModel::getCategoryId).collect(Collectors.toList());
            cateNameMap = categoryService.selectList(categoryService.wrappers().select(CategoryModel::getName, BaseIntEntity::getId).in(categoryIds.size() > 1, BaseIntEntity::getId, categoryIds).eq(categoryIds.size() == 1, BaseIntEntity::getId, categoryIds.get(0))).stream().collect(Collectors.toMap(BaseIntEntity::getId, CategoryModel::getName, (a, b) -> b));
            //List<String> videoIds = result.stream().map(VideoInfoModel::getId).toList();
            //chapterNameMap = videoChapterService.selectList(videoChapterService.wrappers().select(VideoChapterModel::getName, VideoChapterModel::getId).in(chapterIds.size() > 1, VideoChapterModel::getId, chapterIds).eq( chapterIds.size() == 1, VideoChapterModel::getId, chapterIds.get(0))).stream().collect(Collectors.toMap(VideoChapterModel::getId, VideoChapterModel::getName, (a, b) -> b));
        } else {
            cateNameMap = Map.of();
            //chapterNameMap = Map.of();
        }

        result.forEach(videoInfoModel -> {
            videoInfoModel.setCategoryName(cateNameMap.get(videoInfoModel.getCategoryId()));
            videoInfoModel.setChapterName(videoChapterService.selectList(videoChapterService.wrappers().apply("JSON_CONTAINS(video_ids, {0})", "[\"" + videoInfoModel.getAliyunVideoId() + "\"]")).stream().map(VideoChapterModel::getName).collect(Collectors.joining(",")));
        });
        return result;
    }

    ;

    @Override
    protected LambdaQueryWrapper<VideoInfoModel> baseWrapper(VideoInfoModel model, JSONObject otherParam) {
        List<String> idList = null;
        if (StrUtil.isNotBlank(model.getChapterId())) {
            idList = videoChapterService.getById(model.getChapterId()).getVideoIds();
            otherParam.remove("chapterId");
        }
        return super.baseWrapper(model.clearEmptyStringField("name"), otherParam)
                .like(StrUtil.isNotBlank(model.getName()), VideoInfoModel::getName, model.getName()).in(idList != null, VideoInfoModel::getId, idList);
    }

    @GetMapping("/handout/{videoId}")
    public List<VideoHandoutModel> handout(@PathVariable Long videoId) {
        return videoHandoutService.selectList(videoHandoutService.wrappers().eq(VideoHandoutModel::getVideoId, videoId));
    }

    @PostMapping("/upload-handout")
    @Operation(summary = "上传资料")
    public Boolean uploadhandout(@RequestBody VideoHandoutDto videoHandoutDto) {

        videoHandoutDto.getVideoHandoutModel().forEach(videoHandoutModel -> {
            videoHandoutModel.setVideoId(videoHandoutDto.getVideoId());
        });
        return videoHandoutService.insertBatch(videoHandoutDto.getVideoHandoutModel());
    }


    @GetMapping("/list-by-chapter")
    @Operation(summary = "根据章节id获取视频")
    public List<VideoInfoModel> listByChapter(@RequestParam String industryCode,
                                              @RequestParam String examId,
                                              @RequestParam Long categoryId, @RequestParam String columnId, @RequestParam String ChapterId) {
        // var videoIds = videoChapterReService.selectList(videoChapterReService.wrappers().eq(VideoChapterReModel::getChapterId, ChapterId)).stream().map(VideoChapterReModel::getVideoId).toList();
        List<VideoInfoModel> videoList = videoInfoService.selectList(videoInfoService.wrappers().in(VideoInfoModel::getChapterId, ChapterId).orderByAsc(VideoInfoModel::getSort));
        String userId = userContext.currentUserId();
        if (StringUtils.isNotBlank(userId)) {
            var records = recordsGetDataService.getVideoRecordsData(userId, industryCode, examId, categoryId, columnId, ChapterId);
            videoList = videoList.stream().peek(videoInfoModel -> {
                var oneVideoRecord = records.get(videoInfoModel.getId());
                if (oneVideoRecord != null) {
                    videoInfoModel.setWatchDuration(oneVideoRecord.getTi());
                    videoInfoModel.setFs(oneVideoRecord.getFs());
//                    VideoRecordsDtoItem
                }

            }).toList();
        }
        return videoList;
    }

    @PostMapping("/aliyun-auth")
    @Operation(summary = "获取播放凭证")
    public String getVideoPlayAuth(@RequestParam String columnId, @RequestParam String topChapterId, @RequestParam String videoId) throws Exception {
        var isFree = columnConfigReService.configIsFree(columnId, topChapterId);
        if (!isFree) {
            var userId = userContext.currentUserId();
            if (StringUtils.isBlank(userId))
                throw new BizException(AclResultCode.notLogin);
            if (!columnService.currentHaveAuth(null, null, userId, null, columnId, null))
                throw new BizException(AclResultCode.noPower);
        }
        return aliyunVideoPluginsExt.getVideoPlayAuth(videoId);
    }

    @PostMapping("/aliyun-auth-free")
    @Operation(summary = "获取播放凭证")
    public String getVideoPlayAuthFree(@RequestParam String videoId) throws Exception {
        // 必须是首个视频，防止非法获取播放凭证
        QueryWrapper<VideoInfoModel> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("aliyun_video_id", videoId);
        VideoInfoModel videoInfoModel = videoInfoService.selectOne(queryWrapper);
        QueryWrapper<VideoInfoModel> queryWrapper1 = new QueryWrapper<>();
        queryWrapper1.eq("category_id", videoInfoModel.getCategoryId());
        VideoInfoModel videoInfoModel1 = videoInfoService.selectFirst(queryWrapper1);
        if (videoInfoModel1.getAliyunVideoId().equals(videoId)) {
            return aliyunVideoPluginsExt.getVideoPlayAuth(videoId);
        }
        return null;
    }

    @PostMapping("/aliyun-auth-free-play")
    @Operation(summary = "获取播放凭证")
    public String getVideoPlayAuthFreePlay(@RequestParam String videoId, @RequestParam String categoryId) throws Exception {
        // 必须是首个视频，防止非法获取播放凭证
        List<VideoInfoModel> videoTry = ((VideoInfoMapper) videoInfoService.getMapper()).getVideoTry(new Long[]{Long.valueOf(categoryId)});
//        videoInfoMapper
        if (!videoTry.isEmpty()) {
            if (videoTry.get(0).getId().equals(videoId)) {
                return aliyunVideoPluginsExt.getVideoPlayAuth(videoTry.get(0).getAliyunVideoId());
            }
        }
        return null;
    }

    static class Tt {
        String a;
    }

    @Operation(summary = "保存视频播放记录")
    @PostMapping("/save-video-records")
    public void saveVideoRecords(@RequestParam String industryCode,
                                 @RequestParam String examId,
                                 @RequestParam Long categoryId,
                                 @RequestParam String columnId,
                                 @RequestParam String ChapterId,
                                 @RequestParam(required = false) Tt tt,
                                 @ModelAttribute("data") Map<String, VideoRecordsDtoItem> data) {
        var userId = userContext.currentUserId();
        VideoRecordsDto videoRecordsDto = ossRecordsService.putVideoRecordsData(userId, data, industryCode, examId, categoryId, columnId, ChapterId);

        List<String> videoIds = new ArrayList<>();
        List<VideoRecordsModel> videoRecordsModelsInsert = new ArrayList<>();
        data.keySet().forEach(key -> {
            videoIds.add(key);
        });
        QueryWrapper<VideoRecordsModel> videoRecordsModelQueryWrapper = new QueryWrapper<>();
        videoRecordsModelQueryWrapper.eq("user_id", userId)
                .in("video_id", videoIds);
        List<VideoRecordsModel> videoRecordsModels = videoRecordsMapper.selectList(videoRecordsModelQueryWrapper);
        List<VideoRecordsModel> updateModels = videoRecordsModels.stream().map(e -> {
            e.setFs(data.get(e.getVideoId()).getFs());
            e.setWatchDuration(data.get(e.getVideoId()).getTi());
            return e;
        }).toList();

        videoIds.forEach(videoId -> {
            if (!videoRecordsModels.stream().anyMatch(v -> v.getVideoId().equals(videoId))) {
                VideoRecordsModel build = VideoRecordsModel.builder()
                        .chapterId(ChapterId)
                        .examId(examId)
                        .industryCode(industryCode)
                        .columnId(columnId)

                        .updateTime(LocalDateTime.now())
                        .createTime(LocalDateTime.now())
                        .userId(userId)
                        .videoId(videoId)
                        .categoryId(categoryId)
                        .watchDuration(data.get(videoId).getTi())
                        .fs(data.get(videoId).getFs())

                        .build();
                videoRecordsModelsInsert.add(build);
            }
        });

        if (!updateModels.isEmpty()) {
            videoRecordsMapper.batchUpdateTime(updateModels);
        }
        if (!videoRecordsModelsInsert.isEmpty()) {
            videoRecordsMapper.batchInsert(videoRecordsModelsInsert);
        }

//        videoRecordsDto.get("data");
    }

    @Operation(summary = "保存栏目观看记录")
    @PostMapping("/save-lastid-column")
    public void saveLastIdColumn(@RequestParam String industryCode,
                                 @RequestParam String examId,
                                 @RequestParam Long categoryId,
                                 @RequestParam String columnId,
                                 @RequestParam String ChapterId,
                                 @RequestParam String videoId) {
        var userId = userContext.currentUserId();
        var countColumn = recordsGetDataService.getCountColumnVideoRecordsData(userId, industryCode, examId, categoryId, columnId);
        if (countColumn == null) {
            countColumn = new CountVideoRecordsDto();
        }
        countColumn.setLastId(videoId);
        recordsSetDataService.setCountColumnVideoRecordsData(userId, countColumn, industryCode, examId, categoryId, columnId);
    }

    /**
     * 根据vid获取url等信息，移动端需要
     */
    @GetMapping("/GetPlayInfo")
    public GetPlayInfoResponseBody.GetPlayInfoResponseBodyVideoBase getPlayInfo(@RequestParam String videoId) throws Exception {
        return aliyunVideoPluginsExt.getPlayInfo(videoId);
    }

    @GetMapping("/getVideoRecords")
    public Page<VideoInfoModel> getVideoRecords(@RequestParam(defaultValue = "10") Integer size, @RequestParam(defaultValue = "1") Integer current, @RequestParam String industryCode,
                                                @RequestParam String examId,
                                                @RequestParam(required = false) Long categoryId,
                                                @RequestParam(required = false) String columnId) {
        /*
         * 获取某考试下的观看记录
         * */
        var userId = userContext.currentUserId();
        Page<VideoRecordsModel> page = new Page<>(current, size);
        Map<String, Object> params = new HashMap<>();
        params.put("industryCode", industryCode);
        params.put("examId", examId);
        params.put("userId", userId);

        return videoRecordsMapper.getVideoRecords(page, params);
    }

    @DeleteMapping("/delete-video-records")
    public Boolean deleteVideoRecords(@RequestBody List<Integer> ids) {
        var userId = userContext.currentUserId();
        return videoRecordsMapper.deleteBatchIds1(ids, userId);
    }
}
